<?php

class Controller_Commerce extends Controller_Template
{
	public function before()
	{
		parent::before();
		$this->db = Database::instance();
		$this->model = Model::factory('cart');
	}

	public function actionDeleteItem($section, $token)
	{
		session_start();
		if (isset($_SESSION['cart'][$section]) ? count($_SESSION['cart'][$section]) : false) {
			for ($cnt = 0; $cnt < count($_SESSION['cart'][$section]); $cnt++) {
				if ($_SESSION['cart'][$section][$cnt]['token'] == $token) {
					unset($_SESSION['cart'][$section][$cnt]);
					break;
				}
			}
		}
		$this->response->redirect(Request::$controller . 'checkout/');
	}

	public function actionCheckout()
	{
		$this->template->title = 'Checkout';
		$this->addStyle('/styles/autoform.css');
		session_start();
		$orderItems = array();
		$sections = Cart::instance()->sections;
		$items = array();
		if (isset($_SESSION['cart']) ? count($_SESSION['cart']) : false) {
			foreach ($_SESSION['cart'] as $section => $cartItems) {
				foreach ($cartItems as $cartItem) {
					if (isset($sections[$section])) {
						$items[] = array_merge(array('source' => $sections[$section]['source']), $cartItem);
					}
				}
			}
		}
		if (isset($_POST['cart']) ? count($_POST['cart']) : false) {
			$_SESSION['cart'] = $_POST['cart'];
			$this->response->redirect(Request::$uri);
		}
		foreach ($items as $item) {
			try {
				$class = new ReflectionClass(ucfirst($item['source']) == 'Directory' ? 'DirectoryClass' : ucfirst($item['source']));
				$controller = $class->newInstance();
				if ($class->getMethod('validateItem')) {
					if (false !== ($result = $controller->validateItem($item))) {
						$orderItems[] = array_merge(array('source' => $item['source'], 'quantity' => $item['quantity'], 'token' => $item['token']), $result);
					}
				}
			} catch (ReflectionException $e) {
				continue;
			}
		}
		$isDigital = true;
		if (count($orderItems)) {
			foreach ($orderItems as $orderItem) {
				$isDigital &= $sections[$orderItem['section']]['isDigital'];
			}
			$form = new Form('customer');
			$form->text('customer', 'Full name')->rule('required')->attribute('size', 40);
			$form->select('state', array_merge(array('' => ''), Text::$states), 'State')->rule('required');
			$form->text('zip', 'ZIP-code')->rule('required')->attribute('size', 10);
			$form->text('address', 'Address')->rule('required')->attribute('size', 40);
			$form->hidden('delivery', 0);
			$form->text('phone', 'Phone')->attribute('size', 40);
			$form->textarea('comment', 'Comments')->attribute('cols', 30)->attribute('rows', 10);
			$form->submit('submit', 'Checkout');
			if (Request::$method == 'POST') {
				if ($form->validate()) {
					$values = $form->getValues();
					$order = array();
					$order['items'] = $orderItems;
					if (isset($values['delivery'])) {
						$order['delivery'] = ($values['delivery'] ? 1 : 0);
						unset($values['delivery']);
					} else {
						$order['delivery'] = 0;
					}
					$order['customer'] = $values;
					if ($orderId = Cart::instance()->createOrder($order)) {
						unset($_SESSION['cart']);
						if ($order = $this->model->getOrder($orderId)) {
							$this->response->redirect($order['paypal']);
						}
					}
				}
			}
			$this->template->content = new View('checkout');
			if (isset($this->settings['delivery'])) {
				$this->template->content->delivery = $this->settings['delivery'];
			}
			$this->template->content->items = $orderItems;
			$this->template->content->form = $form;
		} else {
			$this->template->content = 'Your cart is empty';
		}
	}

	public function actionConfirmation($result = 'ok')
	{
		$this->template->title = 'Checkout';
		if ($result == 'ok') {
			$this->template->content = 'Thank you.';
		} elseif ($result == 'cancel') {
			$this->template->content = 'Try next time. Thank you.';
		}
	}


	public function actionIpn()
	{
		$this->autoRender = false;
		if ($orderId = $this->validateIpn()) {
			Cart::instance()->setPaid($orderId);
			$this->response->body = 'Payment done';
		} else {
			$this->response->body = 'Payment failed';
		}
	}

	private function log($message, $success = true, $end = false)
	{
		$text = '['.date('m/d/Y g:i A').'] - ' . (($success) ? 'SUCCESS: ' : 'FAILURE: ') . $message . "\n";
		if ($end) {
			$text .= "\n------------------------------------------------------------------\n\n";
		}
		if (!file_exists('_logs/ipn.txt')) {
			file_put_contents('_logs/ipn.txt', '');
		}
		$fp=fopen('_logs/ipn.txt', 'a');
		fwrite($fp, $text);
		fclose($fp);
	}

	private function validateIpn()
	{
		$ipnData = '';
		$ipnResponse = '';
		$this->log('Paypal IPN Intiated by ' . $_SERVER['REMOTE_ADDR'], true);
		if ($this->settings['sandbox']) {
			$url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
		} else {
			$url = 'https://www.paypal.com/cgi-bin/webscr';
		}
		$post = '';
		foreach ($_POST as $k => $v) {
			$ipnData[$k] = $v;
			$post .= $k . '=' . urlencode($v) . '&';
		}
		if (isset($ipnData['txn_type']) ? $ipnData['txn_type'] == 'subscr_signup' : false) {
			$this->log('Subscription sign up.', true, true);
			return false;
		}

		$this->log('Post string: ' . $post, true);
		$post .= 'cmd=_notify-validate';

		$itemNumber = (isset($ipnData['item_number']) ? $ipnData['item_number'] : (isset($ipnData['item_number1']) ? $ipnData['item_number1'] : (isset($ipnData['invoice']) ? $ipnData['invoice'] : '')));
		if (!$itemNumber) {
			$this->log('Invalid IPN request.', false, true);
			return false;
		}
		if (!($order = $this->model->getOrderByToken($itemNumber))) {
			$this->log('Invalid order id.', false, true);
			return false;
		}
		$this->log('Order ID: ' . $order['id'], true);
		if ($this->settings['paypalEmail'] != $ipnData['receiver_email']) {
			$this->log('Invalid reciever email.', false, true);
			return false;
		}
		$gross = (isset($ipnData['mc_gross']) ? $ipnData['mc_gross'] : (isset($ipnData['mc_gross_1']) ? $ipnData['mc_gross_1'] : (isset($ipnData['payment_gross']) ? $ipnData['payment_gross'] : 0)));
		if ($order['delivery']) {
			$order['amount'] += $this->settings['delivery'];
		}
		if ($order['amount'] != $gross || 'USD' != $ipnData['mc_currency']) {
			$this->log('Currency: ' . $ipnData['mc_currency'], true);
			$this->log('Invalid amount. It had to be ' . $order['amount'] . ', but got ' . $gross . ' from IPN.', false, true);
			return false;
		}
		$curl = curl_init($url);
		curl_setopt ($curl, CURLOPT_HEADER, 0);
		curl_setopt ($curl, CURLOPT_POST, 1);
		curl_setopt ($curl, CURLOPT_POSTFIELDS, $post);
		curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt ($curl, CURLOPT_SSL_VERIFYHOST, 1);
		$ipnResponse = curl_exec ($curl);
		curl_close ($curl);
		$this->log('Connection to ' . $url . ' successfuly completed.', true);
		$this->log('IPN response: ' . $ipnResponse, true);
		if (substr_count('VERIFIED', $ipnResponse)) {
			$this->log('IPN successfully verified. Order id is ' . $order['id'] . '.', true, true);
			return $order['id'];
		} else {
			$this->log('IPN validation failed.', false, true);
			return false;
		}
	}

}
